﻿using System.Collections.Generic;
using System.Linq;
using AbstractBugTracker;
using AbstractProducts;
using log4net;
using SmartAssembly;
using Utilities;

namespace Engine.Buggets
{
    internal sealed class NormalCreator<TBug, TBugDef> : ICreatorBugget<TBug>
        where TBug : class, IBug
        where TBugDef : BugDef
    {
        private static readonly ILog s_Log = LogManager.GetLogger("Engine.Buggets.NormalCreator");
        private readonly IBugPresenter<TBug, TBugDef> m_BugPresenter;
        private readonly IBugTracker<TBug, TBugDef> m_BugTracker;

        internal NormalCreator(IBugPresenter<TBug, TBugDef> bugPresenter, IBugTracker<TBug, TBugDef> bugTracker)
        {
            m_BugPresenter = bugPresenter;
            m_BugTracker = bugTracker;
        }

        /// <remarks>
        /// This is partially duplicated in <see cref="SecondaryCreator{TBug,TBugDef}"/>
        /// </remarks>
        public IEnumerable<Tuple<ProcessedReport, TBug>> Run(ProcessedReport processedReport)
        {
            ProductRef productRef = processedReport.ProductBuildRef.ProductRef;
            IExceptionReportHasher exceptionReportHasher = m_BugTracker.GetExceptionReportHasher(productRef);
            IExceptionReportMapper exceptionReportMapper = m_BugTracker.GetExceptionReportMapper(productRef);
            BugRef bugRef = new BugRef(processedReport, exceptionReportHasher, exceptionReportMapper);
            s_Log.InfoFormat("bugRef is\n{0}", bugRef);

            IEnumerable<TBug> bugs = m_BugTracker.Search(bugRef);
            if (!bugs.Any())
            {
                TBugDef bugDef = m_BugTracker.CreateBugDef(bugRef);
                m_BugPresenter.PresentNewBug(processedReport, bugDef);
                TBug bug = m_BugTracker.CreateBug(bugDef);
                bugs = new[] { bug };
            }

            return bugs.Select(x => new Tuple<ProcessedReport, TBug>(processedReport, x));
        }
    }
}
